import EventBus from "@/utils/EventBus";
import axios, { AxiosError } from "axios";

const request = axios.create({
  /**
   *  在打包给后端的时候，这个api的baseURL
   *      要根据下面的情况来处理
   *
   *      1. 当前build出来的目录，是直接放到 自己的 数据服务器 上面的，并且不会跨域
   *            baseURL 直接写服务器的ip和端口或者直接写/就行
   *            但是不一定是在这写死，可能会是在 .env.rod 里面写好的 环境变量 ，通过 process.env.NODE_ENV.xxxx 获取
   *
   *      2. 当前build出来的目录，不是直接放到 数据服务器上的 就会产生跨域请求
   *          要和后端协商，以什么开头来实现跨域 , 当然我们的以什么开头，可能也是直接在 .env 文件里面已经配置好了的
   *
   */
  baseURL: "/api",
  // baseURL: "/",
  timeout: 5000,
});

request.interceptors.request.use(
  (config) => {
    // 本项目几乎所有的接口，都需要带token
    let token = localStorage.getItem("token");
    // if(token && config.headers){
    //   config.headers['x-auth-token'] = token;
    // }
    if (token) {
      config.headers = config.headers || {};
      config.headers["x-auth-token"] = token;
    }
    return config;
  },
  (err) => Promise.reject(err)
);

// 统一的请求出错的捕获分两种：
// 1. 服务器请求的响应状态码是 200 ，但是业务状态码 是自己定义的不同状态码 ---> 需要在 use 的 第一个回调函数里面进行捕获
// 2. 服务器响应回来的状态码不是200 ， 就是我们当前这个项目 ---> 需要在use的第二个回调函数里面进行捕获
request.interceptors.response.use(
  (res) => {
    // 这里负责对响应回来的数据进行处理，因为我们在页面上只需要使用到服务器响应回来的数据，但是axios里面
    // 本来 在请求后得到的 res 是自己内部封装的 res ，里面还要再点一层才能拿到 服务器响应回来的数据
    return res.data;
  },
  (err: AxiosError<IServerResponse<any>>) => {
    // 进行统一的 报错 处理
    // console.log(err);
    // console.log(err.response?.data.message);
    // 先提示用户
    // 提示用户需要使用 useToast 这个hook，但是当前的环境既不是 函数组件 ，也不是 自定义hook，所以这里无法使用 useToast
    // 需要进行逻辑解耦 - 订阅发布模式 - 使用key对应一个数组，数组里面存你要做的逻辑(函数) ，当需要的时候，把数组取出来，一一个把里面的函数调用
    // 进行错误提示的发布
    EventBus.emit("catch_err", err.response?.data);

    // // 如果是登录失效
    // if (err.response?.data.errCode === 1002) {
    //   // 清除token ， Subjects - 只要是跟当前用户相关的缓存，都清除
    //   localStorage.removeItem("token");
    //   sessionStorage.removeItem("subjects");
    //   // 跳转到登录页
    // }

    return Promise.reject(err);
  }
);

export default request;
